/*
 * @Author: Crazy_Debug yangcheng960813@163.com
 * @Date: 2023-05-17 21:34:18
 * @LastEditTime: 2024-07-15 09:42:30
 * @LastEditors: yayalee yangcheng960813@163.com
 * @Description: 
 * @FilePath: \unfinished-challenges\assets\core_cc\_cc.ts
 * 可以输入预定的版权声明、个性签名、空行等
 */

import { Camera, Component, EventTouch, Node, Rect, Slider, UITransform, Vec2, Vec3, __private, find, v2, v3 } from "cc";
import touchEvent from "./touch/touchEvent";

export type __types_globals__Constructor<T = unknown> = new (...args: any[]) => T;

export class _cc {

    /**
    * 异步等待 - Component.scheduleOnce
    * @param cmpt 
    * @param seconds 秒 - 可以指定 0 让回调函数在下一帧立即执行或者在一定的延时之后执行。
    * @returns 
    */
    public static waitCmpt(cmpt: Component, seconds: number = 0): Promise<void> {
        return Coop((resolve) => {
            cmpt.scheduleOnce(() => {
                resolve();
            }, seconds);
        });
    }

    /**
     * 获得物体的包围盒
     * @param node 
     * @param world 
     * @returns 
     */
    public static getRect(node: Node, world: boolean = false) {
        let pos = world ? node.getWorldPosition() : node.getPosition();
        let { width, height, anchorX, anchorY } = node.getComponent(UITransform)!;
        return new Rect(pos.x - width * anchorX, pos.y - height * anchorY, width, height);
    }

    public static A2BNodeSpace(a: Node, b: Node): Vec3 {
        let AworldPos = a.getWorldPosition();
        let pos = b.getComponent(UITransform)!.convertToNodeSpaceAR(AworldPos);
        return v3(pos.x, pos.y);
    }

    /**
     * @description 获取cc组件没有就add上去一个
     * @param node 组件的节点
     * @param cmpt 类名或实现了cc.Component接口的组件类名称 或 cc组件实现类名称 或 cc组件名
     */
    static getCmpt(node: Node, cmpt: string, needAdd?: boolean): Component;
    static getCmpt<T extends Component>(node: Node, cmpt: __types_globals__Constructor<T>, needAdd?: boolean): T
    static getCmpt<T extends Component>(node: Node, cmpt: any, needAdd: boolean = false): T {
        if (!node) { console.error("node is null"); return null!; }
        return node.getComponent(cmpt)! || needAdd && node.addComponent(cmpt);
    }

    /**
     * 设置 position 位置
     * @param node 
     * @param x 
     * @param y 
     * @param z 
     */
    static setPos(node: Node, x: number, y?: number, z?: number): void;
    static setPos(node: Node, x: Vec2, y?: number, z?: number): void;
    static setPos(node: Node, x: Vec3, y?: number, z?: number): void;
    static setPos(node: Node, x: any, y: number, z: number): void {
        if (!node) { return console.error("node is null"); }
        let x1 = 0, y1 = 0, z1 = 0;
        let pos = node.position.clone();
        if (isNumber(x)) {
            x1 = x;
            y1 = isNumber(y) ? y : pos.y;
            z1 = isNumber(z) ? z : pos.z;
        } else if (x instanceof Vec2) {
            x1 = x.x; y1 = x.y; z1 = 0;
        } else if (x instanceof Vec3) {
            x1 = x.x; y1 = x.y; z1 = x.z;
        }
        node.setPosition(x1, y1, z1);
    }

    /**
     * 设置 scale 缩放
     * @param node 
     * @param x 
     * @param y 
     * @param z 
     */
    static setScale(node: Node, x: number, y?: number, z?: number): void;
    static setScale(node: Node, x: Vec2, y?: number, z?: number): void;
    static setScale(node: Node, x: Vec3, y?: number, z?: number): void;
    static setScale(node: Node, x: any, y: number, z: number): void {
        if (!node) { return console.error("node is null"); }
        let x1 = 0, y1 = 0, z1 = 1;
        let pos = node.scale.clone();
        if (isNumber(x)) {
            x1 = x;
            y1 = isNumber(y) ? y : pos.y;
            z1 = isNumber(z) ? z : pos.z;
        } else if (x instanceof Vec2) {
            x1 = x.x; y1 = x.y; z1 = 1;
        } else if (x instanceof Vec3) {
            x1 = x.x; y1 = x.y; z1 = x.z;
        }
        node.setScale(x1, y1, z1);
    }

    /**
     * vec2转换为Vec3
     * @param v2 
     * @returns 
     */
    public static v2Tov3(v2: Vec2, z: number = 0): Vec3 {
        return v3(v2.x, v2.y, z);
    }
    /**
     * vec3转换为Vec2
     * @param v2 
     * @returns 
     */
    public static v3Tov2(v3: Vec3): Vec2 {
        return v2(v3.x, v3.y);
    }
    /**
     * 返回旋转给定弧度后的新向量。
     * @param pos 
     * @param radians 
     * @returns 
     */
    public static rotate(pos: Vec2, angle: number): Vec2
    public static rotate(pos: Vec3, angle: number): Vec3
    public static rotate(pos: Vec2 | Vec3, angle: number): Vec2 | Vec3 {
        let radians = this.angle2Radian(angle);
        let out = pos instanceof Vec2 ? v2() : v3();
        var sin = Math.sin(radians);
        var cos = Math.cos(radians);
        var x = pos.x;
        out.x = cos * x - sin * pos.y;
        out.y = sin * x + cos * pos.y;
        return out;
    }

    /**
     * 弧度值转换为角度值
     * @param radian 弧度值
     * @returns {number} 返回角度
     */
    public static radian2Angle(radian: number): number {
        return radian * 180 / Math.PI;
    }
    /**
    * 角度值转换为弧度值
    * @param {number} angle 角度
    * @returns {number} 返回弧度值
    */
    public static angle2Radian(angle: number): number {
        return angle * Math.PI / 180;
    }


    /**
    * 两个向量获取弧度
    * @param {Vec2} v1 
    * @param {Vec2} v2 
    * @returns {number} radian 弧度
    */
    public static getRadian = (v1: Vec2, v2: Vec2): number => Math.atan2(v2.y - v1.y, v2.x - v1.x);
    /**
     * 获得随机方向
     * @returns {Vec2} 返回一个带方向的随机向量
     */
    public static randomDirection = (): Vec2 => v2(Math.random() - 0.5, Math.random() - 0.5).normalize();

    public static point2Angle(start: Vec2, end: Vec2): number {
        var dx = start.x - end.x;
        var dy = start.y - end.y;
        var dir = v2(dx, dy);
        var angle = dir.signAngle(v2(1, 0));
        var degree = angle / Math.PI * 180;
        return -degree;
    }

    /**矩形与圆形检测 */
    static ComputeCollision(w: number, h: number, r: number, rx: number, ry: number): boolean {
        var dx = Math.min(rx, w * 0.5);
        var dx1 = Math.max(dx, -w * 0.5);
        var dy = Math.min(ry, h * 0.5);
        var dy1 = Math.max(dy, -h * 0.5);
        return (dx1 - rx) * (dx1 - rx) + (dy1 - ry) * (dy1 - ry) <= r * r;
    }

    /**圆形和矩形检测 */
    static circleRect(circle: UITransform, rect: Rect): boolean {
        //圆的半径  
        var radius = circle.width / 2;
        //圆形中心与矩形中心的相对坐标  
        var x = circle.node.position.x - rect.x;
        var y = circle.node.position.y - rect.y;

        var minX = Math.min(x, rect.width * 0.5);
        var maxX = Math.max(minX, -rect.width * 0.5);
        var minY = Math.min(y, rect.height * 0.5);
        var maxY = Math.max(minY, -rect.height * 0.5);
        return (maxX - x) * (maxX - x) + (maxY - y) * (maxY - y) <= radius * radius;
    }

    /**
     * 递归查找返回第一个符合条件的节点
     * @param path 路径 or 名字
     * @param node 从那个节点开始往下找
     * @returns 返回找到的节点
     */
    static find(path: string, node: Node) {
        if (typeof path == 'string' && path.indexOf('/') != -1) {
            return find(path, node);
        } else {
            return this.searchChild(path, node);
        }
    }
    /**
     * 
     * @param name 
     * @param parent 
     * @returns 
     */
    private static searchChild(name: string, parent: Node): Node | null {
        if (!parent) {
            console.error("find parent is null");
            return null;
        }
        var target = parent.getChildByName(name);
        if (target) return target;
        let length = parent.children.length;
        for (let i = 0; i < length; i++) {
            target = this.searchChild(name, parent.children[i]);
            if (target) return target;
        }
        return target;
    }

    /**
     * 节点添加点击事件
     * @param node 节点
     * @param func 方法
     * @param that 
     */
    static click(node: Node, func: (e?: EventTouch, ...agrs: any[]) => void, that?: any) {
        // node?.on(touchEvent.touch_end, func, that);
        this.end(node, func, that);
    }
    /**节点移除点击事件 */
    static $click(node: Node, func?: () => void, that?: any) {
        // node?.off(touchEvent.touch_end, func, that);
        this.$end(node, func, that);
    }
    /**
     * 监听 start 事件
     * @param node 
     * @param func 
     * @param that 
     */
    static start(node: Node, func: (e?: EventTouch, ...agrs: any[]) => void, that?: any) {
        node?.on(touchEvent.touch_start, func, that);
    }
    /**移除 start 事件 */
    static $start(node: Node, func?: () => void, that?: any) {
        node?.off(touchEvent.touch_start, func, that);
    }
    /**
     * 监听 move 事件
     * @param node 
     * @param func 
     * @param that 
     */
    static move(node: Node, func: (e?: EventTouch, ...agrs: any[]) => void, that?: any) {
        node?.on(touchEvent.touch_move, func, that);
    }
    /**移除 move 事件 */
    static $move(node: Node, func?: () => void, that?: any) {
        node?.off(touchEvent.touch_move, func, that);
    }
    /**
     * 监听 end 事件
     * @param node 
     * @param func 
     * @param that 
     */
    static end(node: Node, func: (e?: EventTouch, ...agrs: any[]) => void, that?: any) {
        node?.on(touchEvent.touch_end, func, that);
    }
    /**移除 end 事件 */
    static $end(node: Node, func?: () => void, that?: any) {
        node?.off(touchEvent.touch_end, func, that);
    }
    /**
     * @description slider 滑动事件
     * @param slider 
     * @param func 
     * @param that 
     */
    static slide(slider: Node, func: (e?: EventTouch, ...agrs: any[]) => void, that?: any) {
        slider?.on(touchEvent.slide, func, that);
    }

    static $slide(slider: Node, func: () => void, that?: any) {
        slider?.on(touchEvent.slide, func, that);
    }

    /** 截图 */
    public static captureScreen(camera: Camera, prop?: Node | Rect) {
        // let newTexture = new RenderTexture();
        // let oldTexture = camera.targetTexture;
        // let rec: Rect = rect(0, 0, visibleRect.width, visibleRect.height);
        // if (prop) {
        //     if (prop instanceof Node) {
        //         rec = prop.getBoundingBoxToWorld();
        //     } else {
        //         rec = prop;
        //     }
        // }
        // newTexture.initWithSize(visibleRect.width, visibleRect.height, game['_renderContext'].STENCIL_INDEX8);
        // camera.targetTexture = newTexture;
        // camera.render();
        // camera.targetTexture = oldTexture;

        // let buffer = new ArrayBuffer(rec.width * rec.height * 4);
        // let data = new Uint8Array(buffer);
        // newTexture.readPixels(rec.x, rec.y, rec.width, rec.height, data);
        // return data;
    }

    /** 获得Component的类名 */
    public static getComponentName(com: Function) {
        let arr = com.name.match(/<.*>$/);
        if (arr && arr.length > 0) {
            return arr[0].slice(1, -1);
        }
        return com.name;
    }

}
// if (EDITOR) {
//     console.group('cocos引擎配置');
//     console.log('是否开启抗锯齿',/*  view.isAntiAliasEnabled(), */ macro.ENABLE_WEBGL_ANTIALIAS);
//     console.log('是否开启多点触摸', macro.ENABLE_MULTI_TOUCH);
//     console.log('是否显示左下角调试信息', isDisplayStats());
//     console.log('是否开启瓦片地图的自动裁减功能', macro.ENABLE_TILEDMAP_CULLING);
//     console.log('单次批处理渲染的顶点数量', macro.BATCH_VERTEX_COUNT);
//     console.log('Canvas背景是否支持 alpha 通道', macro.ENABLE_TRANSPARENT_CANVAS);
//     console.log('引擎支持的图片格式', ...macro.SUPPORT_TEXTURE_FORMATS);
//     console.groupEnd();
// }